/*
 * @Author: your name
 * @Date: 2021-06-14 22:09:35
 * @LastEditTime: 2021-06-15 22:30:00
 * @LastEditors: Please set LastEditors
 * @Description: In User Settings Edit
 * @FilePath: \hexo_blog\\192.168.2.100\jzijin\signal_thread.c
 */
#include <stdio.h>
#include <pthread.h>
#include <signal.h>
#include <unistd.h>
#include <time.h>

static pthread_t g_main_thread_id;
static pthread_t g_sub_thread_id;
static pthread_t g_send_sig_thread_id;

static void sig_handler(int signum)
{
    time_t time_s = time(NULL);
    struct tm now_time;
    
    // 信号处理程序调用localtime_r非信号安全函数。
    localtime_r(&time_s, &now_time);
    printf("get signum %d, the thread_id is %lu\n", signum, pthread_self());
}

static void *send_sig_func(void *)
{
    while (1)
    {
        // 发送给main线程处理，不会导致死锁。
        // pthread_kill(g_main_thread_id, SIGUSR1);

        // 发送给send_sig线程，不会导致死锁。
        // pthread_kill(g_send_sig_thread_id, SIGUSR1);

        // 发送给子线程处理，会导致死锁。因子线程本身在调用localtime_r会导致死锁。
        pthread_kill(g_sub_thread_id, SIGUSR1);

        sleep(1);
    }
}

void *call_localtime_r(void *)
{
    time_t time_s = time(NULL);
    struct tm now_time;
    while(1)
    {
        localtime_r(&time_s, &now_time);
    }
}

int main(void)
{
    struct sigaction act;
    sigset_t block_set;

    act.sa_flags = 0;
    sigemptyset(&act.sa_mask);
    act.sa_handler = sig_handler;
    sigaction(SIGUSR1, &act, NULL);

    /* 获取主线程的线程id */
    g_main_thread_id = pthread_self();
    printf("g_main_thread_id = %lu\n", g_main_thread_id);

    pthread_create(&g_sub_thread_id, NULL, call_localtime_r, NULL);
    printf("g_sub_thread_id = %lu\n", g_sub_thread_id);

    /* 发送信号线程 */
    pthread_create(&g_send_sig_thread_id, NULL, send_sig_func, NULL);
    printf("g_send_sig_thread_id = %lu\n", g_send_sig_thread_id);

    /* 注意，省略了错误检查 */

    pthread_join(g_sub_thread_id, NULL);
    pthread_join(g_send_sig_thread_id, NULL);

    return 0;
}